home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 2410 / 2410.xpi / chrome / content / foxmarks-settings.js < prev    next >
Text File  |  2010-01-28  |  45KB  |  1,508 lines

  1. /* 
  2.  Copyright 2005-2008 Foxmarks Inc.
  3.  
  4.  foxmarks-settings.js: implements FoxmarksSettings, an object that wraps
  5.  access to persistent settings, both user settings and internal stored values.
  6.    
  7.  */
  8.  
  9. // TO DO:
  10. // * If user changes username or password, delete our cookie.
  11.  
  12. var Xmarks;
  13. if(Xmarks === undefined){
  14.     Xmarks = {};
  15. }
  16.  
  17. var Cc = Components.classes;
  18. var Ci = Components.interfaces;
  19. var CCon = Components.Constructor;
  20.  
  21. (function() {
  22. var xm = Xmarks;
  23. xm.FOXMARKS_SYNC_REALM = "Foxmarks Sync Login";
  24. xm.FOXMARKS_SYNC_REALM_PIN = "Foxmarks Sync PIN";
  25. xm.SYNC_REALM = "Xmarks Sync Login";
  26. xm.SYNC_REALM_PIN = "Xmarks Sync PIN";
  27.  
  28. xm.Bundle = function() {
  29.   var sb = Components.classes["@mozilla.org/intl/stringbundle;1"]
  30.       .getService(Components.interfaces.nsIStringBundleService)
  31.       .createBundle("chrome://foxmarks/locale/foxmarks.properties");
  32.   return sb;
  33. };
  34.  
  35. xm.UpdateToXMarks = function(){
  36.     var ps = Cc["@mozilla.org/preferences-service;1"].
  37.             getService(Ci.nsIPrefService);
  38.     var foxmarks = ps.getBranch("foxmarks.");
  39.     var doupdate = false;
  40.  
  41.     try {
  42.         doupdate = foxmarks.getIntPref("majorVersion") == 2;
  43.     } catch(e){
  44.         // do nothing
  45.     }
  46.  
  47.     if(doupdate){
  48.         var xmarks = ps.getBranch("extensions.xmarks.");
  49.         var obj = { value: 0 };
  50.         var list = xmarks.getChildList("",obj);
  51.         obj = { value: 0 };
  52.         list = foxmarks.getChildList("",obj);
  53.  
  54.         var len = list.length;
  55.         while(len--){
  56.             var name = list[len];
  57.             var valtype = foxmarks.getPrefType(name);
  58.             switch(valtype){
  59.                 case xmarks.PREF_STRING:
  60.                     xmarks.setCharPref(name, foxmarks.getCharPref(name));
  61.                     break;
  62.                 case xmarks.PREF_INT:
  63.                     xmarks.setIntPref(name, foxmarks.getIntPref(name));
  64.                     break;
  65.                 case xmarks.PREF_BOOL:
  66.                     xmarks.setBoolPref(name, foxmarks.getBoolPref(name));
  67.                     break;
  68.             }
  69.         }
  70.         foxmarks.deleteBranch("");
  71.         ps.savePrefFile(null);     // ensure it gets flushed
  72.         xm.gSettings.correctHashes();
  73.     }
  74. };
  75. // Notify takes the given args object and passes it to observers.
  76. // By convention, args contains at least "status", an integer with
  77. // the following interpretation:
  78. //   0: operation completed successfully.
  79. //   1: operation continues; msg is status update only.
  80. //   2: operation was cancelled by user.
  81. //   3: component finished
  82. //   other: operation failed.
  83. // Similarly, "msg" contains a user-displayable message.
  84.  
  85. xm.Notify = function(args) {
  86.     var os = Cc["@mozilla.org/observer-service;1"]
  87.         .getService(Ci.nsIObserverService);
  88.  
  89.     var str = args.toSource();        
  90.     os.notifyObservers(null, "foxmarks-service", str);
  91. };
  92.  
  93. xm.SetProgressComponentStatus = function(id, phase){
  94.     xm.Notify({status: 3, component: id, phase: phase} );
  95. };
  96. xm.SetProgressMessage = function(msgname) {
  97.     var msg;
  98.     try {
  99.         msg = xm.Bundle().GetStringFromName(msgname);
  100.     } catch(e) {
  101.         msg = "untranslated(" + msgname + ")";
  102.     }
  103.  
  104.     xm.Notify({status: 1, msg: msg} );
  105. };
  106.  
  107. xm._popupCloseState = false;
  108. xm.ClickNewUserPopup = function(){
  109.     xm._popupCloseState = true;
  110.     var panel = document.getElementById("foxmarks-newuserwiz");
  111.     if(panel){
  112.         panel.hidePopup();
  113.     }
  114.     Xmarks.OpenWizard(false, false);
  115. };
  116. xm.NewUserPopupHiding = function(){
  117.     if(xm._popupCloseState){
  118.         return true;
  119.     }
  120.     var panel = document.getElementById("foxmarks-newuserwiz");
  121.     if(panel){
  122.         var TOTALTIME = 1000;
  123.         var  NUMSTEPS = 20;
  124.         var ctr = 0;
  125.         var func = function() {
  126.             var opac = Number(panel.style.opacity);
  127.             if(opac > 0 && ctr < NUMSTEPS){
  128.                 panel.style.opacity = Math.max(opac - (1 / NUMSTEPS), 0);
  129.                 ctr++;
  130.                 window.setTimeout(func, Math.floor(TOTALTIME / NUMSTEPS));
  131.             } else {
  132.                 xm._popupCloseState = true;
  133.                 panel.hidePopup();
  134.             }
  135.  
  136.         };
  137.         window.setTimeout(func, 2000);
  138.         xm._popupCloseState = true;
  139.     }
  140.     return false;
  141. };
  142. xm.CloseNewUserPopup = function(){
  143.     var panel = document.getElementById("foxmarks-newuserwiz");
  144.     if(panel){
  145.         var os = Cc["@mozilla.org/observer-service;1"].
  146.             getService(Ci.nsIObserverService);
  147.         os.notifyObservers(null, "foxmarks-tr","closebubble"); 
  148.         xm._popupCloseState = true;
  149.         panel.hidePopup();
  150.     }
  151. };
  152. xm.NewUserPopup = function(data){
  153.     if(!data || data.status !== 0 || !data.use_bib){
  154.         Xmarks.OpenWizard(false, false);
  155.     } else {
  156.         xm._popupCloseState = false;
  157.         xm.gSettings.wizardRetriesLeft = xm.gSettings.wizardRetriesLeft - 1;
  158.         var panel = document.getElementById("foxmarks-newuserwiz");
  159.         if(panel){
  160.             panel.setAttribute("style", data.popup_style);
  161.             var box = document.getElementById("foxmarks-bubblebox");
  162.             box.setAttribute("style", data.box_style);
  163.  
  164.             box = document.getElementById("foxmarks-bubblecontainer");
  165.             box.setAttribute("style", data.container_style);
  166.  
  167.             box = document.getElementById("foxmarks-bubbletextbox");
  168.             box.setAttribute("style", data.text_style);
  169.  
  170.             box = document.getElementById("foxmarks-bubbletitle");
  171.             box.setAttribute("style", data.title_style);
  172.  
  173.             if(xm.gSettings.is_english){
  174.                 box.setAttribute("value", data.title_english);
  175.             }
  176.  
  177.             box = document.getElementById("foxmarks-bubbleclose");
  178.             box.setAttribute("style", data.close_style);
  179.  
  180.             box = document.getElementById("foxmarks-bubbledesc");
  181.             box.setAttribute("style", data.desc_style);
  182.             if(xm.gSettings.is_english){
  183.                 box.removeChild(box.firstChild);
  184.                 var desc = document.createTextNode(
  185.                     data.desc_english
  186.                 );
  187.                 box.appendChild(desc);
  188.             }
  189.  
  190.             var img = document.getElementById("foxmarks-bubbletr");
  191.             var attrs = [];
  192.             xm.gSettings.sessionID = Date.now().toString(36);
  193.             attrs.push("app="       + "jezebel");
  194.             attrs.push("mid="       + xm.gSettings.machineId);
  195.             attrs.push("sess="      + xm.gSettings.sessionID);
  196.             attrs.push("page="      + "bubblepopup");
  197.             attrs.push("flavor="    + data.flavor);
  198.             attrs.push("no_cache="  + Date.now().toString(36));
  199.  
  200.             var query = attrs.join("&");
  201.             img.src = xm.gSettings.httpProtocol + "tr.xmarks.com/tracking/impressions.gif?" + query;
  202.             panel.openPopup(
  203.                 document.getElementById(data.anchor),
  204.                 data.position,
  205.                 data.posx,
  206.                 data.posy,
  207.                 false,
  208.                 false
  209.             );
  210.             setTimeout(function(){
  211.                 panel.style.opacity = 1.0;
  212.             }, 100);
  213.  
  214.             document.getElementById("foxmarks-bubbleclose").addEventListener(
  215.                 "click",
  216.                 function(e){
  217.                     e.stopPropagation();
  218.                     xm.CloseNewUserPopup();
  219.                 }, 
  220.                 true
  221.             );
  222.         }
  223.     }
  224. };
  225. xm.Alert = function(str){
  226.     var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
  227.         .getService(Components.interfaces.nsIPromptService);
  228.     ps.alert(null,"Xmarks", str);
  229. };
  230.  
  231. xm.MapErrorUrl = function(status) {
  232.     var error = "";
  233.  
  234.     status = status & 0x0000ffff;
  235.  
  236.     try {
  237.         error = xm.Bundle().GetStringFromName("errorurl." + status);
  238.     } catch (e) {
  239.         if(xm.UnknownError(status)){
  240.             error = xm.Bundle().GetStringFromName("errorurl.unknown");
  241.         } else {
  242.             error = "";
  243.         }
  244.     }
  245.  
  246.     return error;
  247. };
  248.  
  249. xm.UnknownError = function(status){
  250.     var result = false;
  251.     status = status & 0x0000ffff;
  252.  
  253.     try {
  254.         xm.Bundle().GetStringFromName("error." + status);
  255.         result = false;
  256.     } catch (e) {
  257.         result = true;
  258.     }
  259.  
  260.     return result;
  261. };
  262. xm.MapErrorMessage = function(status) {
  263.     var error = "";
  264.  
  265.     status = status & 0x0000ffff;
  266.  
  267.     try {
  268.         error = xm.Bundle().GetStringFromName("errormsg." + status);
  269.     } catch (e) {
  270.         if(xm.UnknownError(status)){
  271.             error = xm.Bundle().formatStringFromName(
  272.                 "errormsg.unknown", [status], 1);
  273.         } else {
  274.             error = "";
  275.         }
  276.     }
  277.  
  278.     return error;
  279. }; 
  280. xm.MapError = function(status) {
  281.     var error = "";
  282.  
  283.     status = status & 0x0000ffff;
  284.  
  285.     try {
  286.         error = xm.Bundle().GetStringFromName("error." + status);
  287.     } catch (e) {
  288.         error = xm.Bundle().formatStringFromName("error.unknown", [status], 1);
  289.     }
  290.  
  291.     return error;
  292. }; 
  293.  
  294. /**
  295. * Convert a string containing binary values to hex.
  296. * Shamelessly stolen from nsUpdateService.js
  297. */
  298. function binaryToHex(input) {
  299.     var result = "";
  300.     for (var i = 0; i < input.length; ++i) {
  301.         var hex = input.charCodeAt(i).toString(16);
  302.         if (hex.length == 1)
  303.             hex = "0" + hex;
  304.         result += hex;
  305.     }
  306.     return result;
  307. }
  308.  
  309. xm.hex_md5 = function(string) {
  310.     var arr = new Array();
  311.     
  312.     for (var i = 0; i < string.length; ++i)
  313.         arr[i] = string.charCodeAt(i);
  314.         
  315.     var hash = Components.classes["@mozilla.org/security/hash;1"].
  316.                 createInstance(Components.interfaces.nsICryptoHash);
  317.     hash.initWithString("md5");
  318.     hash.update(arr, arr.length);
  319.     return  binaryToHex(hash.finish(false));
  320. };
  321.  
  322. // Return the version string associated with the currently installed version
  323. xm.ExtensionManagerLiteral = function(value) {
  324.     var rdfs = Components.classes["@mozilla.org/rdf/rdf-service;1"].
  325.         getService(Components.interfaces.nsIRDFService);
  326.     var ds = Components.classes["@mozilla.org/extensions/manager;1"].
  327.         getService(Components.interfaces.nsIExtensionManager).datasource;
  328.     var s = rdfs.GetResource("urn:mozilla:item:foxmarks@kei.com");
  329.     var p = rdfs.GetResource("http://www.mozilla.org/2004/em-rdf#" + value);
  330.     var t = ds.GetTarget(s, p, true);
  331.     if (t instanceof Components.interfaces.nsIRDFLiteral)
  332.         return t.Value;
  333.     else
  334.         return "unknown";
  335. };
  336.  
  337. xm.FoxmarksVersion = function() {
  338.     return xm.ExtensionManagerLiteral("version");
  339. };
  340.  
  341. xm.FoxmarksUpdateAvailable = function() {
  342.     var none = ["none", "unknown"];
  343.  
  344.     return none.indexOf(xm.ExtensionManagerLiteral(
  345.             "availableUpdateURL")) < 0;
  346. };
  347.  
  348. function XmarksSettings() {
  349.     // upgrade to xmarks if possible
  350.     var ps = Cc["@mozilla.org/preferences-service;1"].
  351.             getService(Ci.nsIPrefService);
  352.         
  353.     this.prefs = ps.getBranch("extensions.xmarks.");
  354.     this.ps = ps;
  355. }
  356.  
  357. XmarksSettings.prototype = {
  358.     prefs: null,
  359.  
  360.     // Only call this for uninstalls (it nukes all prefs)
  361.     clearAllPrefs: function(){
  362.         this.pin = "";
  363.         this.password = "";
  364.         this.prefs.deleteBranch("");
  365.     },
  366.     
  367.     getCharPref: function(string, def) {
  368.         var result;
  369.         
  370.         try {
  371.             result = this.prefs.getCharPref(string);
  372.         } catch (e) {
  373.             result = def;
  374.         }
  375.         
  376.         return result;
  377.     },
  378.  
  379.     getIntPref: function(string, def) {
  380.         var result;
  381.         
  382.         try {
  383.             result = this.prefs.getIntPref(string);
  384.         } catch (e) {
  385.             result = def;
  386.         }
  387.         
  388.         return result;
  389.     },
  390.  
  391.  
  392.     getBoolPref: function(string, def) {
  393.         var result;
  394.         
  395.         try {
  396.             result = this.prefs.getBoolPref(string);
  397.         } catch (e) {
  398.             result = def;
  399.         }
  400.         
  401.         return result;
  402.     },
  403.  
  404.  
  405.     formatDate: function(d) {
  406.         return d.toLocaleDateString() + " " + d.toLocaleTimeString();
  407.     },
  408.  
  409.     // get fundamental settings
  410.  
  411.     get username() {
  412.         return this.getCharPref("username", "");
  413.     },
  414.  
  415.     get httpProtocol() {
  416.         return this.securityLevel == 1 ? "https://" : "http://";
  417.     },
  418.  
  419.     get auth() {
  420.         var fms = Cc["@foxcloud.com/extensions/foxmarks;1"].
  421.             getService(Ci.nsIFoxmarksService);
  422.  
  423.         return fms.getAuth();
  424.     },
  425.  
  426.     set auth(pw) {
  427.         var fms = Cc["@foxcloud.com/extensions/foxmarks;1"].
  428.             getService(Ci.nsIFoxmarksService);
  429.  
  430.         fms.setAuth(pw);
  431.     },
  432.     get sessionPin() {
  433.         var fms = Cc["@foxcloud.com/extensions/foxmarks;1"].
  434.             getService(Ci.nsIFoxmarksService);
  435.  
  436.         return fms.getPin();
  437.     },
  438.  
  439.     set sessionPin(pw) {
  440.         var fms = Cc["@foxcloud.com/extensions/foxmarks;1"].
  441.             getService(Ci.nsIFoxmarksService);
  442.  
  443.         fms.setPin(pw);
  444.     },
  445.     get sessionPassword() {
  446.         var fms = Cc["@foxcloud.com/extensions/foxmarks;1"].
  447.             getService(Ci.nsIFoxmarksService);
  448.  
  449.         return fms.getPassword();
  450.     },
  451.  
  452.     set sessionPassword(pw) {
  453.         var fms = Cc["@foxcloud.com/extensions/foxmarks;1"].
  454.             getService(Ci.nsIFoxmarksService);
  455.  
  456.         fms.setPassword(pw);
  457.     },
  458.  
  459.     findLogin: function(host, realm, username) {
  460.         var logins = [];
  461.         try {
  462.             var lm = Cc["@mozilla.org/login-manager;1"].
  463.                 getService(Ci.nsILoginManager);
  464.             logins = lm.findLogins({}, host, null, realm);
  465.         } catch (e) {
  466.             Xmarks.LogWrite("Failed retrieving passwords from login manager." +
  467.                     "Files corrupted? Reported error is " + e);
  468.         }
  469.         for (var i = 0; i < logins.length; ++i) {
  470.             if (logins[i].username == username)
  471.                 return logins[i].password;
  472.         }
  473.         return null;
  474.     },
  475.  
  476.     removePIN: function(){
  477.         var lm = Cc["@mozilla.org/login-manager;1"].
  478.             getService(Ci.nsILoginManager);
  479.         var nsli = new CCon("@mozilla.org/login-manager/loginInfo;1",
  480.             Ci.nsILoginInfo, "init");
  481.         var oldli = new nsli(this.host, null, xm.SYNC_REALM_PIN, 
  482.             this.username, this.pinNoPrompt, "", "");
  483.  
  484.         lm.removeLogin(oldli);
  485.         this.sessionPin = "";
  486.     },
  487.  
  488.     set pin(pin) {
  489.         if (!this.rememberPin) {
  490.             this.sessionPin = pin;
  491.         } else {
  492.             if ("@mozilla.org/login-manager;1" in Cc) {
  493.                 // Can't set password without username.
  494.                 if (!this.username)
  495.                     return;
  496.                 var lm = Cc["@mozilla.org/login-manager;1"].
  497.                     getService(Ci.nsILoginManager);
  498.                 var nsli = new CCon("@mozilla.org/login-manager/loginInfo;1",
  499.                     Ci.nsILoginInfo, "init");
  500.                 var newli = new nsli(this.host, null, xm.SYNC_REALM_PIN, 
  501.                     this.username, pin, "", "");
  502.                 var oldli = new nsli(this.host, null, xm.SYNC_REALM_PIN, 
  503.                     this.username, this.pinNoPrompt, "", "");
  504.                 try {
  505.                     lm.modifyLogin(oldli, newli);
  506.                 } catch (e) {
  507.                     lm.addLogin(newli);
  508.                 }
  509.             }
  510.         }
  511.     },
  512.  
  513.     get pin() {
  514.  
  515.         var pw = this.pinNoPrompt;
  516.  
  517.         if (pw != null)
  518.             return pw;
  519.  
  520.         var pin = { value: "" };
  521.         var remember = { value: this.rememberPin };
  522.  
  523.         var sb = xm.Bundle().GetStringFromName;
  524.         var rv = Cc["@mozilla.org/embedcomp/prompt-service;1"].
  525.              getService(Ci.nsIPromptService).
  526.              promptPassword(null, sb("appname.long"), 
  527.                  sb("prompt.pin"),
  528.                   pin,
  529.                  sb("prompt.rememberpin"),
  530.                  remember);
  531.  
  532.         if (!rv) {
  533.             throw 2;
  534.         }
  535.  
  536.         this.pin = pin.value;
  537.         this.rememberPin = remember.value;
  538.  
  539.         return pin.value;
  540.     },
  541.  
  542.     get pinNoPrompt() {
  543.         if (!this.rememberPin && this.sessionPin) {
  544.             return this.sessionPin;
  545.         }
  546.  
  547.         if (this.rememberPin) {
  548.             var pin = this.findLogin(this.host, xm.SYNC_REALM_PIN, 
  549.                 this.username);
  550.             if (pin) return pin;
  551.  
  552.             var oldhost = this.host == "sync.xmarks.com"
  553.                 ? "sync.foxmarks.com" : this.host;
  554.             pin = this.findLogin(oldhost, xm.FOXMARKS_SYNC_REALM_PIN, 
  555.                 this.username);
  556.             if (pin) return pin;
  557.         }
  558.         return null;    // Couldn't fetch pin.
  559.     },
  560.  
  561.     get password() {
  562.  
  563.         var pw = this.passwordNoPrompt;
  564.  
  565.         if (pw != null)
  566.             return pw;
  567.  
  568.         var username = { value: this.username };
  569.         var password = { value: "" };
  570.         var remember = { value: this.rememberPassword };
  571.  
  572.         var sb = xm.Bundle().GetStringFromName;
  573.         var rv = Cc["@mozilla.org/embedcomp/prompt-service;1"].
  574.              getService(Ci.nsIPromptService).
  575.              promptUsernameAndPassword(null, sb("appname.long"), 
  576.                  sb("prompt.usernamepassword"),
  577.                  username, password,
  578.                  sb("prompt.rememberpassword"),
  579.                  remember);
  580.  
  581.         if (!rv) {
  582.             throw 2;
  583.         }
  584.  
  585.         this.rememberPassword = remember.value;
  586.         this.username = username.value;
  587.         this.password = password.value;
  588.  
  589.         return password.value;
  590.     },
  591.  
  592.     get passwordNoPrompt() {
  593.         if (!this.rememberPassword && this.sessionPassword) {
  594.             return this.sessionPassword;
  595.         }
  596.  
  597.         if (!this.rememberPassword) {
  598.             return null;
  599.         }
  600.  
  601.         var pw = this.findLogin(this.host, xm.SYNC_REALM, this.username);
  602.         if (pw) return pw;
  603.  
  604.         // Next try foxmarks realm.
  605.         var oldhost = this.host == "sync.xmarks.com" ? 
  606.             "sync.foxmarks.com" : this.host;
  607.         pw = this.findLogin(oldhost, xm.FOXMARKS_SYNC_REALM, this.username);
  608.         if (pw) return pw;
  609.  
  610.         return null;    // couldn't fetch password
  611.     },
  612.  
  613.     _calcHash: function(host){
  614.         var fms = Cc["@foxcloud.com/extensions/foxmarks;1"].
  615.             getService(Ci.nsIFoxmarksService);
  616.  
  617.         return xm.hex_md5((this.useOwnServer ? 
  618.                 this.url : host + this.username) + 
  619.             fms.getStorageEngine("bookmarks")).slice(16)
  620.             + ".";
  621.     },
  622.     get hash() {
  623.         return this._calcHash(this.host);
  624.     },
  625.             
  626.     get lastSynchDate() {
  627.         return this.getCharPref(this.hash + "lastSynchDate", "");
  628.     },
  629.  
  630.     get haveSynced() {
  631.         return this.lastSynchDate != "";
  632.     },
  633.  
  634.     getLastSyncDate: function(syncType){
  635.         if(syncType == "bookmarks")
  636.             return this.getCharPref(this.hash + "lastSynchDate", "");
  637.         else
  638.             return this.getCharPref(this.hash + syncType + "-lastSynchDate",
  639.                     "");
  640.     },
  641.     
  642.     getHaveSynced: function(syncType){
  643.         return this.getLastSyncDate(syncType) != "";
  644.  
  645.     },
  646.  
  647.     setLastSyncDate: function(syncType, string){
  648.         if(syncType == "bookmarks")
  649.             return this.prefs.setCharPref(this.hash + "lastSynchDate", string);
  650.         else
  651.             return this.prefs.setCharPref(this.hash + syncType + "-lastSynchDate",
  652.                     string);
  653.     },
  654.  
  655.     get minutesSinceLastSync() {
  656.         if (!this.haveSynced)
  657.           return 0;
  658.       
  659.         var syncMS = new Date(this.lastSynchDate).getTime();
  660.         var nowMS = Date.now();
  661.         return (nowMS - syncMS) / 60000;
  662.   
  663.     },
  664.   
  665.     get daysSinceLastUpdateNag() {
  666.         if (!this.lastNagDate)
  667.             return Infinity;
  668.         var updateMS = new Date(this.lastNagDate).getTime();
  669.         var nowMS = Date.now();
  670.         return (nowMS - updateMS) / (60000 * 60 * 24);
  671.     },
  672.   
  673.     get lastNagDate() {
  674.         return this.getCharPref("lastNagDate", null);
  675.     },
  676.     
  677.     set lastNagDate(string) {
  678.         this.prefs.setCharPref("lastNagDate", string);
  679.     },
  680.     
  681.     get lastSynchDisplayDate() {
  682.         if (!this.haveSynced) {
  683.             return xm.Bundle().GetStringFromName("msg.neversynced");
  684.         } else {
  685.             return this.formatDate(new Date(this.lastSynchDate));
  686.         }
  687.     },
  688.  
  689.     setEtag: function(syncType, string){
  690.         if(syncType == "bookmarks"){
  691.             this.prefs.setCharPref(this.hash + "etag", string);
  692.         }
  693.         else {
  694.             this.prefs.setCharPref(this.hash + 
  695.                     "-" + syncType + "-etag", string);
  696.         }
  697.     },
  698.     getEtag: function(syncType){
  699.         if(syncType == "bookmarks"){
  700.             return this.getCharPref(this.hash + "etag", "");
  701.         }
  702.         else {
  703.             return this.getCharPref(this.hash + "-" + syncType + "-etag", "");
  704.         }
  705.     },
  706.     
  707.     
  708.     setToken: function(syncType, string){
  709.         if(syncType == "bookmarks"){
  710.             return this.prefs.setCharPref(this.hash + "token", string);
  711.         }
  712.         else {
  713.             return this.prefs.setCharPref(this.hash + "-" + syncType + "-token", string);
  714.         }
  715.  
  716.     },
  717.     getToken: function(syncType){
  718.         if(syncType == "bookmarks"){
  719.             return this.getCharPref(this.hash + "token", "");
  720.         }
  721.         else {
  722.             return this.getCharPref(this.hash + "-" + syncType + "-token", "");
  723.         }
  724.  
  725.     },
  726.     
  727.     get writeCount() {
  728.         return this.getIntPref("writeCount", 0);
  729.     },
  730.  
  731.     get lastError() {
  732.         return this.getIntPref("lastError", 0);
  733.     },
  734.     set lastError(err){
  735.         this.prefs.setIntPref("lastError", err);
  736.     },
  737.     get synchOnTimer() {
  738.         return this.getBoolPref("synchOnTimer", true);
  739.     },
  740.     get useBaselineCache() {
  741.         return this.getBoolPref("memory-useBaselineCache", true);
  742.     },
  743.     get forceGC() {
  744.         return this.getBoolPref("memory-forceGC", false);
  745.     },
  746.  
  747.     isSyncEnabled: function(syncType){
  748.         return this.getBoolPref("sync-"+syncType, syncType == "bookmarks");
  749.     },
  750.  
  751.     setSyncEnabled: function(syncType, val){
  752.         this.prefs.setBoolPref("sync-"+syncType, val);
  753.         // If password sync is being disabled, clear our sync status
  754.         // so that if we're reenabled we start from scratch. This prevents
  755.         // problems that might occur if the user changed their PIN during
  756.         // the hiatus.
  757.         if (syncType == "passwords" && val == false) {
  758.             this.setLastSyncDate("passwords", "");
  759.         }
  760.     },
  761.     
  762.     mustMerge: function(syncType){
  763.         return this.getBoolPref("mergereq-"+syncType, false);
  764.     },
  765.     setMustMerge: function(syncType, val){
  766.         this.prefs.setBoolPref("mergereq-"+syncType, val);
  767.     },
  768.     mustUpload: function(syncType){
  769.         return this.getBoolPref("uploadreq-"+syncType, false);
  770.     },
  771.     setMustUpload: function(syncType, val){
  772.         this.prefs.setBoolPref("uploadreq-"+syncType, val);
  773.     },
  774.     get autoSynchFreq() {
  775.         return this.getIntPref("autoSynchFreq", 60);
  776.     },
  777.     
  778.     get syncOnShutdown() {
  779.         return this.getIntPref("syncOnShutdown", true) != 0;
  780.     },
  781.  
  782.     get syncOnShutdownAsk() {
  783.         return this.getBoolPref("syncOnShutdownAsk", true);
  784.     },
  785.     
  786.     get debugUI() {
  787.         return this.getBoolPref("debugUI", false);
  788.     },
  789.     
  790.     get wizardPrefs() {
  791.         return this.getCharPref("wizardPrefURL", "/FX/wiz.json");
  792.     },
  793.     set wizardPrefs(val) {
  794.         this.prefs.setCharPref("wizardPrefURL", val);
  795.     },
  796.     get serpPrefix() {
  797.         return this.getCharPref("serpPrefix", "xmarksserp");
  798.     },
  799.     set serpPrefix(val) {
  800.         this.prefs.setCharPref("serpPrefix", val);
  801.     },
  802.     get iframePrefix() {
  803.         return this.getCharPref("iframePrefix", "xmarksas");
  804.     },
  805.     set iframePrefix(val) {
  806.         this.prefs.setCharPref("iframePrefix", val);
  807.     },
  808.     get iframeregex() {
  809.         return this.getCharPref("iframeregex", "");
  810.     },
  811.     set iframeregex(val) {
  812.         this.prefs.setCharPref("iframeregex", val);
  813.     },
  814.     get abgroup() {
  815.         return this.getCharPref("abgroup", "*:C");
  816.     },
  817.     set abgroup(val) {
  818.         this.prefs.setCharPref("abgroup", val);
  819.     },
  820.     get wizardWarning() {
  821.         return this.getBoolPref("wizardDoWarning", true);
  822.     },
  823.     set wizardWarning(v){
  824.         this.prefs.setBoolPref("wizardDoWarning", v);
  825.     },
  826.     get wizardRetriesLeft(){
  827.         return this.getIntPref("wizardRetriesLeft", 5);
  828.     },
  829.  
  830.     set wizardRetriesLeft(v){
  831.         this.prefs.setIntPref("wizardRetriesLeft", v);
  832.     },
  833.  
  834.     get lastWizardBubble(){
  835.         return this.getCharPref("wizardLastBubble", "");
  836.     },
  837.  
  838.     set lastWizardBubble(v){
  839.         this.prefs.setCharPref("wizardLastBubble", v);
  840.     },
  841.     
  842.     get wizardMinTimeExpired(){
  843.         var nowMS = Date.now();
  844.         var lastMS = this.lastWizardBubble == "" ? 0 : new Date(this.lastWizardBubble).getTime();
  845.         return (nowMS - lastMS) >= (24 * 3600 * 1000);
  846.     },
  847.  
  848.     wizardResetMinTime: function(){
  849.         this.lastWizardBubble = this.NowAsGMT;
  850.     },
  851.  
  852.     get wizardSuppress() {
  853.         return this.getBoolPref("wizardNoShow", false);
  854.     },
  855.   
  856.     set wizardSuppress(bool) {
  857.        this.prefs.setBoolPref("wizardNoShow", bool);
  858.     },
  859.  
  860.     get disableIfMatchOnPut() {
  861.         return this.getBoolPref("disableIfMatchOnPut", false);
  862.     },
  863.  
  864.     set enableLogging(bool) {
  865.         this.prefs.setBoolPref("enableLogging", bool);
  866.     },
  867.     get enableLogging() {
  868.         return this.getBoolPref("enableLogging", true);
  869.     },
  870.  
  871.     get rememberPassword() {
  872.         return this.getBoolPref("rememberPassword", true);
  873.     },
  874.  
  875.     set rememberPassword(bool) {
  876.         this.prefs.setBoolPref("rememberPassword", bool);
  877.     },
  878.  
  879.  
  880.     get rememberPin() {
  881.         return this.getBoolPref("rememberPin", true);
  882.     },
  883.  
  884.     set rememberPin(bool) {
  885.         this.prefs.setBoolPref("rememberPin", bool);
  886.     },
  887.  
  888.     set username(string) {
  889.         string = string.replace(/^\s+|\s+$/g, '')
  890.         if (string != this.username) {
  891.             this.prefs.setCharPref("username", string);
  892.             this.ClearCredentials();
  893.         }
  894.     },
  895.     
  896.     /**
  897.      * Returns true if the user has a master password set and false otherwise.
  898.      */
  899.  
  900.     // Adapted from 
  901.     // mxr.mozilla.org/mozilla/source/browser/components/preferences/security.js
  902.  
  903.     get masterPasswordSet() {
  904.         var secmodDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].
  905.             getService(Ci.nsIPKCS11ModuleDB);
  906.         var slot = secmodDB.findSlotByName("");
  907.         if (slot) {
  908.             var status = slot.status;
  909.             var hasMP = status != Ci.nsIPKCS11Slot.SLOT_UNINITIALIZED &&
  910.                 status != Ci.nsIPKCS11Slot.SLOT_READY;
  911.             return hasMP;
  912.         } else {
  913.             // XXX I have no bloody idea what this means
  914.             return false;
  915.         }
  916.     },
  917.  
  918.     set password(password) {
  919.         if (this.passwordNoPrompt != password) {
  920.             this.ClearCredentials();
  921.         }
  922.         if (!this.rememberPassword) {
  923.             this.sessionPassword = password;
  924.         } else {
  925.             if(!password)
  926.                 password = "";
  927.             if ("@mozilla.org/login-manager;1" in Cc) {
  928.                 // Can't set password without username.
  929.                 if (!this.username)
  930.                     return;
  931.                 var lm = Cc["@mozilla.org/login-manager;1"].
  932.                     getService(Ci.nsILoginManager);
  933.                 var nsli = new CCon("@mozilla.org/login-manager/loginInfo;1",
  934.                     Ci.nsILoginInfo, "init");
  935.                 var newli = new nsli(this.host, null, xm.SYNC_REALM, 
  936.                     this.username, password, "", "");
  937.                 var oldli = new nsli(this.host, null, xm.SYNC_REALM, 
  938.                     this.username, this.passwordNoPrompt, "", "");
  939.                 try {
  940.                     if(password.length == 0){
  941.                         lm.removeLogin(oldli);
  942.                     }
  943.                     else {
  944.                         lm.modifyLogin(oldli, newli);
  945.                     }
  946.                 } catch (e) {
  947.                     if(password.length > 0)
  948.                         lm.addLogin(newli);
  949.                 }
  950.             }
  951.         }
  952.     },
  953.     
  954.     ClearCredentials: function() {
  955.         var cm = Cc["@mozilla.org/cookiemanager;1"].
  956.             getService(Ci.nsICookieManager);
  957.         cm.remove(".staging.xmarks.com", "SYNCD_AUTH", "/", false);
  958.         cm.remove(".xmarks.com", "SYNCD_AUTH", "/", false);
  959.         this.auth = "";
  960.     },
  961.  
  962.     set lastSynchDate(string) {
  963.         this.prefs.setCharPref(this.hash + "lastSynchDate", string);
  964.     },
  965.  
  966.     set writeCount(integer) {
  967.         this.prefs.setIntPref("writeCount", integer);
  968.     },
  969.         
  970.     set autoSynchFreq(integer) {
  971.         this.prefs.setIntPref("autoSynchFreq", integer);
  972.     },
  973.     
  974.     set synchOnTimer(bool) {
  975.         this.prefs.setBoolPref("synchOnTimer", bool);
  976.     },
  977.     
  978.     set syncOnShutdown(integer) {
  979.         this.prefs.setIntPref("syncOnShutdown", integer);
  980.     },
  981.     
  982.     set syncOnShutdownAsk(bool) {
  983.         this.prefs.setBoolPref("syncOnShutdownAsk", bool);
  984.     },
  985.  
  986.     set debugUI(bool) {
  987.         this.prefs.setBoolPref("debugUI", bool);
  988.     },
  989.  
  990.     set serpEnabled(v){
  991.         this.prefs.setBoolPref("enableSERP", v);
  992.     },
  993.  
  994.     get serpEnabled(){
  995.         return this.getBoolPref("enableSERP", true);
  996.     },
  997.  
  998.     set simsiteEnabled(v){
  999.         this.prefs.setBoolPref("enableSimSite", v);
  1000.     },
  1001.  
  1002.     get simsiteEnabled(){
  1003.         return this.getBoolPref("enableSimSite", true);
  1004.     },
  1005.  
  1006.     get serpRegex(){
  1007.         return this.getCharPref("SERPRegEx", "(http:\/\/www\.google\..+\/.*[?&]q=([^&]+))|(http:\/\/[-a-zA-Z]+\.start3\.mozilla\.com\/search\?.*[?&]q=([^&]+))|(http:\/\/search\.yahoo\.com\/search?.*[?&]p=([^&]+))|(http:\/\/search\.(msn|live)\.com\/results\.aspx?.*[?&]q=([^&]+))");
  1008.     },
  1009.     set serpRegex(v){
  1010.         this.prefs.setCharPref("SERPRegEx", v);
  1011.     },
  1012.     get serpMaxItems(){
  1013.         return this.getIntPref("SERPMaxItems", 3);
  1014.     },
  1015.  
  1016.     set serpMaxItems(val) {
  1017.         this.prefs.setIntPref("SERPMaxItems", val);
  1018.     },
  1019.     set tagSuggestionsEnabled(v){
  1020.         this.prefs.setBoolPref("enableTagSuggestions", v);
  1021.     },
  1022.  
  1023.     get is_english(){
  1024.         var lang = this.lang;
  1025.         if(lang){
  1026.             return lang.split("-")[0] == 'en';
  1027.         }
  1028.         return true;
  1029.     },
  1030.     get lang(){
  1031.         var prefs = Components.classes["@mozilla.org/preferences-service;1"]
  1032.             .getService(Components.interfaces.nsIPrefBranch2);
  1033.         var lang = prefs.getComplexValue("intl.accept_languages",
  1034.                 Ci.nsIPrefLocalizedString).data;
  1035.  
  1036.         if(lang){
  1037.             var a = lang.split(",");
  1038.             if(a.length){
  1039.                 return a[0];
  1040.             }
  1041.         }
  1042.         return lang;
  1043.     },
  1044.     get tagSuggestionsEnabled() {
  1045.         var result;
  1046.         
  1047.         try {
  1048.             result = this.prefs.getBoolPref("enableTagSuggestions");
  1049.         } catch (e) {
  1050.             try {
  1051.                 var prefs = Components.classes["@mozilla.org/preferences-service;1"]
  1052.                                 .getService(Components.interfaces.nsIPrefBranch2);
  1053.                 var lang = prefs.getComplexValue("intl.accept_languages",
  1054.                     Ci.nsIPrefLocalizedString).data;
  1055.                 result = lang.substr(0, 2) == "en";
  1056.                 this.tagSuggestionsEnabled = result;
  1057.             } catch(f){
  1058.                 result = false;
  1059.             }
  1060.         }
  1061.         
  1062.         return result;
  1063.     },
  1064.     
  1065.     // get calculated settings
  1066.     get calcPath() {
  1067.         return this.path.replace("{username}", this.username);
  1068.     },
  1069.        
  1070.     get NowAsGMT() {
  1071.         var d = new Date();
  1072.         return d.toGMTString();
  1073.     },
  1074.     
  1075.  
  1076.     SyncComplete: function(syncType) {
  1077.         this.setLastSyncDate(syncType, this.NowAsGMT);
  1078.         // TODO - remove the last sync by type; it's really unnecssary and causes issues if bookmarks are being synced
  1079.         if(!this.isSyncEnabled("bookmarks")){
  1080.             this.setLastSyncDate("bookmarks", this.NowAsGMT);
  1081.         }
  1082.     },
  1083.  
  1084.     // Additions to support Sync2
  1085.     get useOwnServer() {
  1086.         return this.getBoolPref("useOwnServer", false);
  1087.     },
  1088.  
  1089.     set useOwnServer(bool) {
  1090.         this.prefs.setBoolPref("useOwnServer", bool);
  1091.     },
  1092.  
  1093.     set url(u) {
  1094.         this.prefs.setCharPref("url-bookmarks", u);
  1095.     },
  1096.  
  1097.     get url() {
  1098.         return this.getCharPref("url-bookmarks",
  1099.             this.getCharPref("url", ""));
  1100.     },
  1101.  
  1102.     set passwordurl(u) {
  1103.         this.prefs.setCharPref("url-passwords", u);
  1104.     },
  1105.  
  1106.     get passwordurl() {
  1107.         return this.getCharPref("url-passwords", "");
  1108.     },
  1109.  
  1110.     set hideStatusIcon(b) {
  1111.         this.prefs.setBoolPref("hideStatusIcon", b);
  1112.         var os = Cc["@mozilla.org/observer-service;1"].
  1113.             getService(Ci.nsIObserverService);
  1114.         os.notifyObservers(null, "foxmarks-statechange", 
  1115.             xm.gSettings.hideStatusIcon ?  "hide" : "show")
  1116.     },
  1117.  
  1118.     get hideStatusIcon() {
  1119.         return this.getBoolPref("hideStatusIcon", false);
  1120.     },
  1121.  
  1122.     getUrlWithUsernameAndPassword: function(syncType){
  1123.         var url;
  1124.         if(syncType == "bookmarks")
  1125.             url = this.url;
  1126.         else
  1127.             url = this.getCharPref("url-" + syncType, "");
  1128.             
  1129.         var user = this.username;
  1130.         var pw = this.password;
  1131.         
  1132.         if (pw.length) {
  1133.             user += ":" + pw;
  1134.         }
  1135.  
  1136.         if (user.length) {
  1137.             user += "@";
  1138.         }
  1139.  
  1140.         return url.replace("://", "://" + user);
  1141.     },
  1142.  
  1143.     get majorVersion() {
  1144.         return this.getIntPref("majorVersion", 1);
  1145.     },
  1146.  
  1147.     set majorVersion(ver) {
  1148.         this.prefs.setIntPref("majorVersion", ver);
  1149.     },
  1150.  
  1151.     get currVersion(){
  1152.         return this.getCharPref("lastUpdateVersion", "");
  1153.     },
  1154.  
  1155.     set currVersion(ver){
  1156.         this.prefs.setCharPref("lastUpdateVersion", ver);
  1157.     },
  1158.     get getRevisionLimit(){
  1159.         return this.getIntPref("getRevisionLimit", 50);
  1160.     },
  1161.     set getRevisionLimit(val){
  1162.         this.prefs.setIntPref("getRevisionLimit", val);
  1163.     },
  1164.     get host() {
  1165.         if (this.useOwnServer) {
  1166.             var exp = /(.*):\/\/([^\/]*)/;
  1167.             var result = this.url.match(exp);
  1168.             if (!result) {
  1169.                 return null;
  1170.             } else {
  1171.                 return result[1] + "://" + result[2];
  1172.             }
  1173.         } else {
  1174.             return this.getCharPref("host-bookmarks",
  1175.                        this.getCharPref("host", "sync.xmarks.com"));
  1176.         }
  1177.     },
  1178.  
  1179.     setDebugOption: function(opt, val){
  1180.         this.prefs.setBoolPref("debug-" + opt, val);
  1181.     },
  1182.     getDebugOption: function(opt){
  1183.         return this.getBoolPref("debug-" + opt, false);
  1184.     },
  1185.     getUnitTestOption: function(opt){
  1186.         return this.getIntPref("unittest-" + opt, 0);
  1187.     },
  1188.     getServerHost: function(syncType){
  1189.         if(syncType == "bookmarks" || this.useOwnServer)
  1190.             return this.host;
  1191.         else
  1192.             return this.getCharPref("host-" + syncType, "sync.xmarks.com");
  1193.     },
  1194.     
  1195.     get maxUserTags(){
  1196.         return this.getIntPref("maxusertags", 1000);
  1197.     },
  1198.     get numTurboTags(){
  1199.         return this.getIntPref("turbotagctr", 0);
  1200.     },
  1201.     set numTurboTags(num){
  1202.         this.prefs.setIntPref("turbotagctr", num);
  1203.     },
  1204.  
  1205.  
  1206.     get myHost() {
  1207.         return this.getCharPref("host-my", "my.xmarks.com");
  1208.     },
  1209.     get apiHost() {
  1210.         return this.getCharPref("host-api", "api.xmarks.com");
  1211.     },
  1212.     set apiHost(val) {
  1213.         this.prefs.setCharPref("host-api", val);
  1214.     },
  1215.     get driftHost() {
  1216.         return this.getCharPref("host-drift", "www.xmarks.com");
  1217.     },
  1218.     set driftHost(val) {
  1219.         this.prefs.setCharPref("host-drift", val);
  1220.     },
  1221.     get staticHost() {
  1222.         return this.getCharPref("host-static", "static.xmarks.com");
  1223.     },
  1224.     set staticHost(val) {
  1225.         this.prefs.setCharPref("host-static", val);
  1226.     },
  1227.     get trHost() {
  1228.         return this.getCharPref("host-tr", "tr.xmarks.com");
  1229.     },
  1230.     set trHost(val) {
  1231.         this.prefs.setCharPref("host-tr", val);
  1232.     },
  1233.     get acctMgrHost() {
  1234.         return this.useOwnServer ? "" : 
  1235.             this.getCharPref("host-login",
  1236.                 this.getCharPref("acctMgrHost",
  1237.                     this.host.replace("sync", "login")
  1238.                 )
  1239.             );
  1240.     },
  1241.  
  1242.     get truncateLog(){
  1243.         return this.getBoolPref("truncateLog", true);
  1244.  
  1245.     },
  1246.     get webHost() {
  1247.         return this.useOwnServer ? "www.xmarks.com" : 
  1248.             this.getCharPref("host-www",
  1249.                 this.getCharPref("acctMgrHost",
  1250.                     this.host.replace("sync", "www")
  1251.                 )
  1252.             );
  1253.     },
  1254.     get wizardUrl() {
  1255.         return this.getCharPref("wizardUrl", "https://" + 
  1256.             this.acctMgrHost + "/wizard");
  1257.     },
  1258.  
  1259.     // -1: never synced
  1260.     //  0: likely synced in prior installation
  1261.     //  > 0: definitely synced
  1262.     get currentRevision() {
  1263.         return this.getIntPref(this.hash + "currentRevision", -1);
  1264.     },
  1265.  
  1266.     set currentRevision(cv) {
  1267.         if (cv != this.currentRevision) {
  1268.             this.prefs.setIntPref(this.hash + "currentRevision", cv);
  1269.             this.ps.savePrefFile(null);     // ensure it gets flushed
  1270.         }
  1271.     },
  1272.  
  1273.     GetSyncRevision: function(syncType) {
  1274.         if(syncType == "bookmarks")
  1275.             return this.getIntPref(this.hash + "currentRevision", -1);
  1276.         else    
  1277.             return this.getIntPref(this.hash + syncType + "-currentRevision", -1);
  1278.     },
  1279.  
  1280.     SetSyncRevision: function(syncType,cv) {
  1281.         if (cv != this.GetSyncRevision(syncType)) {
  1282.             if(syncType == "bookmarks")
  1283.                 this.prefs.setIntPref(this.hash + "currentRevision", cv);
  1284.             else
  1285.                 this.prefs.setIntPref(this.hash + syncType + "-currentRevision", cv);
  1286.             this.ps.savePrefFile(null);     // ensure it gets flushed
  1287.         }
  1288.     },
  1289.     get securityLevel() {
  1290.         // -1: use cleartext throughout
  1291.         //  0: use SSL for auth, cleartext otherwise (default)
  1292.         //  1: use SSL everywhere
  1293.         return this.getIntPref("securityLevel", 0);
  1294.     },
  1295.  
  1296.     set securityLevel(level) {
  1297.         this.prefs.setIntPref("securityLevel", level);
  1298.     },
  1299.  
  1300.     get disableIconSync() {
  1301.         return this.getBoolPref("disableIconSync", false);
  1302.     },
  1303.  
  1304.     get disableDirtyOnBatch() {
  1305.         return this.getBoolPref("disableDirtyOnBatch", false);
  1306.     },
  1307.  
  1308.     set machineId(val){
  1309.         this.prefs.setCharPref("machineId", val);
  1310.     },
  1311.     get machineId() {
  1312.         var id = this.getCharPref("machineId", null);
  1313.         if (!id) {
  1314.             var cookieMgr = Components.classes["@mozilla.org/cookiemanager;1"]
  1315.                             .getService(Components.interfaces.nsICookieManager);
  1316.  
  1317.             for (var e = cookieMgr.enumerator; e.hasMoreElements();) {
  1318.                 var cookie = e.getNext().QueryInterface(Components.interfaces.nsICookie); 
  1319.                 if(cookie.host == ".xmarks.com" && cookie.name == "xplatid"){
  1320.                     LogWrite("using xplatid for mid");
  1321.                     id = cookie.value;
  1322.                     break;
  1323.                 }
  1324.             }
  1325.             if(!id){
  1326.                 id = Date.now().toString(36);
  1327.             }
  1328.             this.prefs.setCharPref("machineId", id);
  1329.         }
  1330.         return id;
  1331.     },
  1332.  
  1333.     get serverVersion() {
  1334.         return this.getIntPref("serverVersion", 0);
  1335.     },
  1336.  
  1337.     set serverVersion(val) {
  1338.         this.prefs.setIntPref("serverVersion", val);
  1339.     },
  1340.     get viewId() {
  1341.         return this.getIntPref(this.hash + "viewId", 0);
  1342.     },
  1343.  
  1344.     set viewId(vid) {
  1345.         this.prefs.setIntPref(this.hash + "viewId", vid);
  1346.     },
  1347.  
  1348.     _stPref: function(undec, id, v){
  1349.         if(undec){
  1350.             return "UST-" + id + "-" + v;
  1351.         }
  1352.         return "ST-" + id + "-" + v;
  1353.     },
  1354.     getST: function(undec,id){
  1355.         var result = {};
  1356.         var val;
  1357.  
  1358.         val = this.getIntPref(this._stPref(undec,id, "d"), 0);
  1359.         if(val) result["d"] = val;
  1360.         val = this.getIntPref(this._stPref(undec,id, "dc"), 0);
  1361.         if(val) result["dc"] = val;
  1362.         val = this.getIntPref(this._stPref(undec,id, "u"), 0);
  1363.         if(val) result["u"] = val;
  1364.         val = this.getIntPref(this._stPref(undec,id, "uc"), 0);
  1365.         if(val) result["uc"] = val;
  1366.         val = this.getIntPref(this._stPref(undec,id, "na"), 0);
  1367.         if(val) result["na"] = val;
  1368.         val = this.getIntPref(this._stPref(undec,id, "h"), 0);
  1369.         if(val) result["h"] = val;
  1370.  
  1371.         return result;
  1372.     },
  1373.     incrST: function(id, key, undec){
  1374.         var name;
  1375.  
  1376.         name = this._stPref(undec,id, key);
  1377.         this.prefs.setIntPref(name, this.getIntPref(name, 0) + 1);
  1378.  
  1379.     },
  1380.     clearST: function(id){
  1381.         this.prefs.setIntPref(this._stPref(true, id, "d"),0);
  1382.         this.prefs.setIntPref(this._stPref(true, id, "dc"),0);
  1383.         this.prefs.setIntPref(this._stPref(true, id, "u"),0);
  1384.         this.prefs.setIntPref(this._stPref(true, id, "uc"),0);
  1385.         this.prefs.setIntPref(this._stPref(true, id, "na"),0);
  1386.         this.prefs.setIntPref(this._stPref(true, id, "h"),0);
  1387.         this.prefs.setIntPref(this._stPref(false, id, "d"),0);
  1388.         this.prefs.setIntPref(this._stPref(false, id, "dc"),0);
  1389.         this.prefs.setIntPref(this._stPref(false, id, "u"),0);
  1390.         this.prefs.setIntPref(this._stPref(false, id, "uc"),0);
  1391.         this.prefs.setIntPref(this._stPref(false, id, "na"),0);
  1392.         this.prefs.setIntPref(this._stPref(false, id, "h"),0);
  1393.     },
  1394.  
  1395.     get trSERP() {
  1396.         return this.getCharPref("trSERP", "");
  1397.     },
  1398.  
  1399.     set trSERP(val) {
  1400.         this.prefs.setCharPref("trSERP", val);
  1401.     },
  1402.     get bibBug() {
  1403.         return this.getCharPref("bibBug", "/FX/xmarks_bib.png");
  1404.     },
  1405.  
  1406.     set bibBug(val) {
  1407.         this.prefs.setCharPref("bibBug", val);
  1408.     },
  1409.  
  1410.     get viewName() {
  1411.         return this.getCharPref(this.hash + "viewName", this.viewId ?
  1412.             String(this.viewId) : 
  1413.             xm.Bundle().GetStringFromName("profile.globalname"));
  1414.     },
  1415.  
  1416.     set viewName(name) {
  1417.         this.prefs.setCharPref(this.hash + "viewName", name);
  1418.     },
  1419.  
  1420.     get syncShortcutKey() {
  1421.         return this.getCharPref("shortcut.SyncNow", "");
  1422.     },
  1423.  
  1424.     get siteinfoDialogShortcutKey() {
  1425.         return this.getCharPref("shortcut.SiteInfo", "");
  1426.     },
  1427.     get openSettingsDialogShortcutKey() {
  1428.         return this.getCharPref("shortcut.OpenSettings", "");
  1429.     },
  1430.  
  1431.     get privateBrowsing() {
  1432.         try {
  1433.             var pbs = Cc["@mozilla.org/privatebrowsing;1"]
  1434.                     .getService(Ci.nsIPrivateBrowsingService);
  1435.             return pbs.privateBrowsingEnabled;
  1436.         } catch (e) {
  1437.             return false;
  1438.         }
  1439.     },
  1440.  
  1441.     correctHashes: function(){
  1442.         var oldhash = "";
  1443.         // if we are now using the default host, we must
  1444.         // have used sync.foxmarks.com before
  1445.         Xmarks.LogWrite("Upgrading to 3.0: correcting hashes");
  1446.         Xmarks.LogWrite("Current Host: " + this.host);
  1447.         if(this.host == "sync.xmarks.com"){
  1448.             oldhash = this._calcHash("sync.foxmarks.com");
  1449.  
  1450.             Xmarks.LogWrite("Hashes Need Correction");
  1451.             // change all the hosts
  1452.             this.prefs.setCharPref(this.hash + "lastSynchDate", 
  1453.                 this.getCharPref(oldhash + "lastSynchDate", ""));
  1454.             this.prefs.setCharPref(this.hash + "passwords-lastSynchDate", 
  1455.                 this.getCharPref(oldhash + "passwords-lastSynchDate", ""));
  1456.             this.prefs.setIntPref(this.hash + "currentRevision", 
  1457.                 this.getIntPref(oldhash + "currentRevision", -1));
  1458.             this.prefs.setIntPref(this.hash + "passwords-currentRevision", 
  1459.                 this.getIntPref(oldhash + "passwords-currentRevision", -1));
  1460.             this.prefs.setIntPref(this.hash + "viewId", 
  1461.                 this.getIntPref(oldhash + "viewId", 0));
  1462.             this.prefs.setCharPref(this.hash + "viewName", 
  1463.                 this.getCharPref(oldhash + "viewName", this.viewId ?
  1464.                     String(this.viewId) : 
  1465.                     xm.Bundle().GetStringFromName("profile.globalname")
  1466.             ));
  1467.         } else {
  1468.             oldhash = this.hash;
  1469.         }
  1470.  
  1471.         // bookmark baseline 
  1472.         var dirname = Cc['@mozilla.org/file/directory_service;1']
  1473.             .getService(Ci.nsIProperties)
  1474.             .get('ProfD', Ci.nsIFile);
  1475.         var file = Cc['@mozilla.org/file/directory_service;1']
  1476.             .getService(Ci.nsIProperties)
  1477.             .get('ProfD', Ci.nsIFile);
  1478.         var fromname = "foxmarks-baseline-" + oldhash + "json";
  1479.         var toname = "xmarks-baseline-" + this.hash + "json";
  1480.  
  1481.         try {
  1482.             file.append(fromname);
  1483.             file.moveTo(dirname, toname);
  1484.         } catch(e){
  1485.             // don't do anything if file doesn't exist
  1486.         }
  1487.  
  1488.         // password baseline
  1489.         file = Cc['@mozilla.org/file/directory_service;1']
  1490.             .getService(Ci.nsIProperties)
  1491.             .get('ProfD', Ci.nsIFile);
  1492.         fromname = "foxmarks-password-baseline-" + oldhash + "json";
  1493.         toname = "xmarks-password-baseline-" + this.hash + "json";
  1494.  
  1495.         try {
  1496.             file.append(fromname);
  1497.             file.moveTo(dirname, toname);
  1498.         } catch(e){
  1499.             // don't do anything if file doesn't exist
  1500.         }
  1501.  
  1502.         this.ps.savePrefFile(null);     // ensure it gets flushed
  1503.     }
  1504. }
  1505.  
  1506. xm.gSettings = new XmarksSettings();
  1507. })();
  1508.